﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using GameSchool.Models.OnTheFlyModels;
using GameSchool.Repository;
using M = GameSchool.Models;
using GameSchool.Extra;

namespace GameSchool.Controllers
{
	/// <summary>
	/// CourseController sér um alla virkni tengda námskeiðum 
	/// GameSchool kerfisins. 
	/// </summary> 
	/// 
    [HandleError]
	[Authorize]
	public class CourseController : Controller
	{
        IGameSchoolRepository m_data = RepositoryMaster.CurrentRepository;

        // GET: /Course/
        public ActionResult CourseIndex()
        {
            ICollection<Models.OnTheFlyModels.CourseOverviewItem> model = null;

            Models.Person loggedOnPerson;

            if (UserInfo.IsAuthenticated) 
			{

                loggedOnPerson = UserInfo.GetLoggedOnPerson();

                // Access control
                ViewData["HasCreateNewAccess"] = loggedOnPerson.IsAdmin || loggedOnPerson.IsTeacher;

                // Sækja öll námskeið.
                ICollection<Models.Course> courses = m_data.Courses.Where(x => x.StateTypeValue != (Int16)CustomTypes.CourseStateType.Inactive).ToList();

                model = (from course in courses
                        orderby course.CourseName
                         select new Models.OnTheFlyModels.CourseOverviewItem(loggedOnPerson.PersonId, course)
                        ).ToList();

                return View(model);
            }
            return View();
        }

        public ActionResult SidebarCourses()
        {
            ICollection<Models.OnTheFlyModels.CourseOverviewItem> coursesOverview = new List<Models.OnTheFlyModels.CourseOverviewItem>();

            Models.Person loggedOnPerson;

            if (UserInfo.IsAuthenticated)
            {
                loggedOnPerson = UserInfo.GetLoggedOnPerson();
                bool isCourseFinished = false;

                coursesOverview = (from c in m_data.Courses
                                    join st in m_data.StudentCourses on c.CourseId equals st.CourseId
                                    join p in m_data.Persons on st.StudentId equals p.PersonId
                                    orderby c.CourseName ascending
                                    where c.StateTypeValue == (Int16)CustomTypes.CourseStateType.Active
                                    && p.PersonId == loggedOnPerson.PersonId
                                    && st.Active && (!(st.Completed))
                                    select new CourseOverviewItem()
                                    {
                                        CourseId = c.CourseId,
                                        CourseName = c.CourseName,
                                        CourseDescription = c.Description,
                                        CourseECTS = c.Ects
                                    }).ToList() ;

                // Because EF can only handle single datareader at we need 
                // to loop through the courses afterwards and add additional info.
                foreach (var i in coursesOverview)
                {
                    i.LevelParticipatingInfos = GetLevelInfos(loggedOnPerson.PersonId, i.CourseId, ref isCourseFinished);
                }
            }
            return View(coursesOverview);
        }

        private Models.OnTheFlyModels.LevelParticipateInfoList GetLevelInfos(int personId, int courseId, ref bool isCourseFinished)
        {
            bool saveDataNeeded = false;
            bool lastLevelPartWasFinished = false;

            Models.LevelParticipate lvlPart;
            
            Models.OnTheFlyModels.LevelParticipateInfoList levelList = new Models.OnTheFlyModels.LevelParticipateInfoList();

            levelList.AddRange((from l in m_data.Levels
                                where l.CourseId == courseId
                                orderby l.LevelNumber ascending
                            select new LevelParticipateInfo { Level = l }
                                ).ToList());

            foreach (LevelParticipateInfo lpi in levelList)
            {
                lastLevelPartWasFinished = false;
                lvlPart = m_data.LevelParticipates.Where(x => x.StudentId == personId && x.LevelId == lpi.Level.LevelId).FirstOrDefault();

                if (lvlPart == null)
                {
                    // Nemandi ekki byrjaður á þessu leveli.
                    // Látum hann byrja!
                    lvlPart = new M.LevelParticipate();
                    lvlPart.Level = lpi.Level;
                    lvlPart.OpenDate = DateTime.Today;
                    lvlPart.StateType = CustomTypes.LevelParticipateStateType.Open;
                    lvlPart.StudentId = personId;
                    
                    lpi.LevelParticipate = lvlPart;
                    m_data.LevelParticipates.Add(lvlPart);
                    saveDataNeeded = true;
                    break;
                }

                lpi.LevelParticipate = lvlPart;

                if (lvlPart.StateType == CustomTypes.LevelParticipateStateType.Finished) { 
                    // Nemandi hefur lokið þessu leveli.
                    // Svo við höldum áfram niður listann..
                    lastLevelPartWasFinished = true; // Ef við klárum listann með þessu haki þá hefur nemandinn klárað námskeiðið!
                    continue;
                }

                // Ef þetta level er opið, þá viljum við vinna með það.
                if (lvlPart.StateType == CustomTypes.LevelParticipateStateType.Open)
                {
                    // Ef levelið er útrunnið, þá merkjum við það ólokið
                    if (lvlPart.OpenDate.AddDays(lpi.Level.DaysToFinish) < DateTime.Today)
                    {
                        lvlPart.StateType = CustomTypes.LevelParticipateStateType.Finished;
                        lastLevelPartWasFinished = true; // Ef við klárum listann með þessu haki þá hefur nemandinn klárað námskeiðið!
                        saveDataNeeded = true;
                    }
                    else
                    { 
                       // Þetta level er opið, og ekki útrunnið. 
                       // Þá er það einfaldlega levelið sem notandi er á.
                       break; // Þurfum því ekki að halda áfram niður listann.
                    }
                }
            }
            // Ef við klárum listann með þessu haki þá hefur nemandinn klárað námskeiðið!
            if (lastLevelPartWasFinished)
            {
                isCourseFinished = true;
            }

            if (saveDataNeeded)
            {
                m_data.SaveChanges();
            }
            return levelList;
        }

        // GET: /Course/Details/5
        public ActionResult DetailsCourse(int id)
        {
            Models.Person loggedOnPerson;

            if (UserInfo.IsAuthenticated)
            {
                loggedOnPerson = UserInfo.GetLoggedOnPerson();

                bool isCourseFinished = false;

                Models.Course course = (from c in m_data.Courses
                                        where c.CourseId == id
                                        select c).FirstOrDefault();

                if (course == null)
                {
                    return CourseIndex();
                }

                Models.StudentCourse myRegistration = course.Students.Where(x => x.StudentId == loggedOnPerson.PersonId && x.Active).FirstOrDefault();

                if (myRegistration != null)
                {
                    if (myRegistration.Completed)
                    {
                        ViewData["CourseCompleted"] = true;
                    }
                    else
                    {
                        // Notandi er skráður sem nemandi. Svo við viljum birta LevelInfos á síðunni.
                        ViewData["CourseLevelInfos"] = GetLevelInfos(loggedOnPerson.PersonId, id, ref isCourseFinished);

                        if (isCourseFinished)
                        {
                            myRegistration.Completed = true;
                            m_data.SaveChanges();
                        }
                    }
                }
                ViewData["VideoLectures"] = VideoLecturesByCourseId(id);
                return View(course);
            }
            return CourseIndex();
		}

		public ActionResult MyCourses()	//Skilar yfirliti yfir þau námskeið sem notandi er skráður í eða fyrir
		{
            Models.Person loggedOnPerson;
            IEnumerable<Models.OnTheFlyModels.CourseOverviewItem> model = new List<Models.OnTheFlyModels.CourseOverviewItem>();

            if (UserInfo.IsAuthenticated)
            {
                loggedOnPerson = UserInfo.GetLoggedOnPerson();


                model = (from i in m_data.Courses
                             join m in m_data.StudentCourses on i.CourseId equals m.CourseId
                             where m.StudentId == loggedOnPerson.PersonId
                             && i.StateTypeValue == (Int16)CustomTypes.CourseStateType.Active
                             select new Models.OnTheFlyModels.CourseOverviewItem() { CourseId = i.CourseId, CourseName = i.CourseName, CourseECTS = i.Ects, RegType = CustomTypes.CourseRegType.Student }
                             ).Union(
                            from i in m_data.Courses
                            join m in m_data.TeacherCourses on i.CourseId equals m.CourseId
                            where m.TeacherId == loggedOnPerson.PersonId
                            && i.StateTypeValue != (Int16)CustomTypes.CourseStateType.Inactive
                            select new Models.OnTheFlyModels.CourseOverviewItem() { CourseId = i.CourseId, CourseName = i.CourseName, CourseECTS = i.Ects, RegType = CustomTypes.CourseRegType.Teacher }
                            );
            }
            return View(model);
		}
		
		// GET: /Course/Create
		[Authorize(Roles = "Teachers")]
        public ActionResult CreateCourse()
        {
            return View();
        } 

        // POST: /Course/Create
        [HttpPost]
		[Authorize(Roles = "Teachers")]
        public ActionResult CreateCourse(M.Course course)
        {
            Models.Person loggedOnPerson = Extra.UserInfo.GetLoggedOnPerson();
            if (loggedOnPerson != null)
            {
                UpdateModel(course);

                course.EntryDate = DateTime.Now;
                course.EntryBy = loggedOnPerson.PersonId;

                m_data.Courses.Add(course);
                m_data.SaveChanges();
            }

           return RedirectToAction("CourseIndex");
        }
        
	/*	public ActionResult Namskeidinmin()
		{
			// Sækja öll námskeið.
            ICollection<Models.Course> courses = m_data.Courses.Where(x => x.StateTypeValue != (Int16)CustomTypes.CourseStateType.Inactive).ToList();

			var model = (from course in courses
					 orderby course.CourseName
					 select new Models.OnTheFlyModels.CourseOverviewItem(,course)).ToList();			
			return View(model);
		} */


        // GET: /Course/Edit/5
        public ActionResult EditCourse(int id)
        {
        	var model = m_data.Courses.Find(id);
			return View(model);
        }

		// POST: /Course/Edit/5
		[HttpPost]
		//[Authorize(Roles = "Teachers")]
        public ActionResult EditCourse(int id, M.Course course)
        {
            try
            {
                var item = (from n in m_data.Courses
                            where n.CourseId == id
                            select n).SingleOrDefault();
                
                if (item != null)
                {
                    UpdateModel(item);
                    m_data.SaveChanges();
                    return RedirectToAction("CourseIndex");
                }
                else
                {
                    return RedirectToAction("Error");
                }
            }
            catch
            {
                return View();
            }
        }

		public ActionResult LevelOverView(int id)
        {
            Models.OnTheFlyModels.LevelOverviewList levelOverview = new LevelOverviewList();
            levelOverview.CourseName = m_data.Courses.Find(id).CourseName;
            
            levelOverview.Add(new M.OnTheFlyModels.LevelOverviewItem() { CourseName = "rapp kurs 103", LevelNumber = 1, LevelName = "easy level", State = Extra.CustomTypes.LevelParticipateStateType.Open });
            levelOverview.Add(new M.OnTheFlyModels.LevelOverviewItem() { CourseName = "rapp kurs 103", LevelNumber = 2, LevelName = "not easy level", State = Extra.CustomTypes.LevelParticipateStateType.Locked });

            return View(levelOverview);
        }

        // GET: /Course/RegisterForCourse/1
        [Authorize(Roles = "Students")]
        public ActionResult StudentRegisterForCourse(int id)
        {

            Models.Person loggedOnPerson;

            if (UserInfo.IsAuthenticated)
            {
                loggedOnPerson = UserInfo.GetLoggedOnPerson();

                // Get the course.
                Models.Course course = m_data.Courses.Where(x => x.CourseId == id && x.StateTypeValue == (Int16)Extra.CustomTypes.CourseStateType.Active).FirstOrDefault();

                // Access control
                ViewData["HasCreateNewAccess"] = loggedOnPerson.IsAdmin || loggedOnPerson.IsTeacher;

                if (course == null)
                {
                    ViewData["RegisterResult"] = "Námskeið er ekki virkt.";
                    return View("CourseIndex");
                }

                bool amIRegisteredForCourse = (course.Students.Where(x => x.StudentId == loggedOnPerson.PersonId && x.Active).Count() > 0);

                if (amIRegisteredForCourse)
                {
                    ViewData["RegisterResult"] = "Nemandi er nú þegar skráður.";
                    return View("CourseIndex");
                }

                try
                {
                    course.RegisterStudent(loggedOnPerson, loggedOnPerson.PersonId);
                    m_data.SaveChanges();
                    ViewData["RegisterResult"] = string.Format("Nemandi hefur verið skráður í námskeiðið '{0}'.", course.CourseName);
                }
                catch (Exception)
                {
                    ViewData["RegisterResult"] = "Villa kom upp við að skrá nemanda í námskeið!";
                    throw;
                }
            }
            return View("CourseIndex");
        }

        private ICollection<Models.VideoLecture> VideoLecturesByCourseId(int id)
        {
            ICollection<Models.VideoLecture> vids = (from c in m_data.Courses
                                                     join l in m_data.Levels on c.CourseId equals l.CourseId
                                                     join lp in m_data.LevelParticipates on l.LevelId equals lp.LevelId
                                                     join a in m_data.Assignments on l.LevelId equals a.LevelId
                                                     join v in m_data.VideoLectures on a.AssignmentId equals v.AssignmentId
                                                     where c.StateTypeValue == (Int16)CustomTypes.CourseStateType.Active &&
                                                     l.Active &&
                                                     lp.StateTypeValue != (Int16)CustomTypes.LevelParticipateStateType.Locked &&
                                                     a.Active &&
                                                     v.Active &&
                                                     c.CourseId == id
                                                     orderby l.LevelNumber descending, v.EntryDate descending
                                                     select v).Distinct().ToList();
            return vids;
        }

        public ViewResult VideoLectures(int id)
        {
            return View(VideoLecturesByCourseId(id));
        }
    }
}
